from typing import Type
from bcat.gtp.serde.dev2.iseq_access import ISeqAccess 

from bcat.gtp.serde.error import PairEndError

from bcat.gtp.serde.dev2.ideserializer import IDeserializer
from bcat.gtp.serde.dev2.ireader import IReader
from bcat.gtp.serde.dev2.valid.ivalidate import IValidate

from bcat.gtp.serde.dev2.impl.special_char import SpecialChar

class SeqAccess(ISeqAccess):
    
    def __init__(self, deserializer: IDeserializer):
        self.__deserializer = deserializer
        self.__first = True

    def deserializer(self):
        return self.__deserializer 
    
    def has_next_element(self):
        reader: IReader = self.deserializer().reader()
        if self.__first:
            byte = reader.peek_or_raise()
            if SpecialChar.is_not_value_begin(byte):
                raise Exception("not the begin byte of value") #TODO:
            else:
                self.__first = False
                return True
        else:
            byte = reader.peek_or_raise()
            if SpecialChar.is_pair_separator(byte): # this is ","
                reader.eat()
                byte = reader.peek_or_raise() 
                if SpecialChar.is_not_value_begin(byte):
                    raise Exception("not the begin byte of value") #TODO:
                else:
                    return True
            elif SpecialChar.is_array_end(byte):
                return False
            else:
                msg = "unknow byte:({}:{}), expect:(}} or ,) for test has_next_element".format(chr(byte) if byte <= 0x8f else byte, byte)
                raise PairEndError(reader.position(), msg)

    def next_element(self, element_type: Type[IValidate]):
        return element_type().validate(self.deserializer())
    
